﻿using System.Collections.Generic;
using Godot.core.io;
using Godot.core.os;

namespace Godot.core
{
    public class TranslationServer : Object
    {
        public static string[] locale_list =
        #region ____locale_list____
        {
            "ar", //  Arabic
            "ar_AE", //  Arabic (United Arab Emirates)
            "ar_BH", //  Arabic (Bahrain)
            "ar_DZ", //  Arabic (Algeria)
            "ar_EG", //  Arabic (Egypt)
            "ar_IQ", //  Arabic (Iraq)
            "ar_JO", //  Arabic (Jordan)
            "ar_KW", //  Arabic (Kuwait)
            "ar_LB", //  Arabic (Lebanon)
            "ar_LY", //  Arabic (Libya)
            "ar_MA", //  Arabic (Morocco)
            "ar_OM", //  Arabic (Oman)
            "ar_QA", //  Arabic (Qatar)
            "ar_SA", //  Arabic (Saudi Arabia)
            "ar_SD", //  Arabic (Sudan)
            "ar_SY", //  Arabic (Syria)
            "ar_TN", //  Arabic (Tunisia)
            "ar_YE", //  Arabic (Yemen)
            "be", //  Belarusian
            "be_BY", //  Belarusian (Belarus)
            "bg", //  Bulgarian
            "bg_BG", //  Bulgarian (Bulgaria)
            "ca", //  Catalan
            "ca_ES", //  Catalan (Spain)
            "cs", //  Czech
            "cs_CZ", //  Czech (Czech Republic)
            "da", //  Danish
            "da_DK", //  Danish (Denmark)
            "de", //  German
            "de_AT", //  German (Austria)
            "de_CH", //  German (Switzerland)
            "de_DE", //  German (Germany)
            "de_LU", //  German (Luxembourg)
            "el", //  Greek
            "el_CY", //  Greek (Cyprus)
            "el_GR", //  Greek (Greece)
            "en", //  English
            "en_AU", //  English (Australia)
            "en_CA", //  English (Canada)
            "en_GB", //  English (United Kingdom)
            "en_IE", //  English (Ireland)
            "en_IN", //  English (India)
            "en_MT", //  English (Malta)
            "en_NZ", //  English (New Zealand)
            "en_PH", //  English (Philippines)
            "en_SG", //  English (Singapore)
            "en_US", //  English (United States)
            "en_ZA", //  English (South Africa)
            "es", //  Spanish
            "es_AR", //  Spanish (Argentina)
            "es_BO", //  Spanish (Bolivia)
            "es_CL", //  Spanish (Chile)
            "es_CO", //  Spanish (Colombia)
            "es_CR", //  Spanish (Costa Rica)
            "es_DO", //  Spanish (Dominican Republic)
            "es_EC", //  Spanish (Ecuador)
            "es_ES", //  Spanish (Spain)
            "es_GT", //  Spanish (Guatemala)
            "es_HN", //  Spanish (Honduras)
            "es_MX", //  Spanish (Mexico)
            "es_NI", //  Spanish (Nicaragua)
            "es_PA", //  Spanish (Panama)
            "es_PE", //  Spanish (Peru)
            "es_PR", //  Spanish (Puerto Rico)
            "es_PY", //  Spanish (Paraguay)
            "es_SV", //  Spanish (El Salvador)
            "es_US", //  Spanish (United States)
            "es_UY", //  Spanish (Uruguay)
            "es_VE", //  Spanish (Venezuela)
            "et", //  Estonian
            "et_EE", //  Estonian (Estonia)
            "fi", //  Finnish
            "fi_FI", //  Finnish (Finland)
            "fr", //  French
            "fr_BE", //  French (Belgium)
            "fr_CA", //  French (Canada)
            "fr_CH", //  French (Switzerland)
            "fr_FR", //  French (France)
            "fr_LU", //  French (Luxembourg)
            "ga", //  Irish
            "ga_IE", //  Irish (Ireland)
            "hi", //  Hindi (India)
            "hi_IN", //  Hindi (India)
            "hr", //  Croatian
            "hr_HR", //  Croatian (Croatia)
            "hu", //  Hungarian
            "hu_HU", //  Hungarian (Hungary)
            "in", //  Indonesian
            "in_ID", //  Indonesian (Indonesia)
            "is", //  Icelandic
            "is_IS", //  Icelandic (Iceland)
            "it", //  Italian
            "it_CH", //  Italian (Switzerland)
            "it_IT", //  Italian (Italy)
            "iw", //  Hebrew
            "iw_IL", //  Hebrew (Israel)
            "ja", //  Japanese
            "ja_JP", //  Japanese (Japan)
            "ja_JP_JP", //  Japanese (Japan,JP)
            "ko", //  Korean
            "ko_KR", //  Korean (South Korea)
            "lt", //  Lithuanian
            "lt_LT", //  Lithuanian (Lithuania)
            "lv", //  Latvian
            "lv_LV", //  Latvian (Latvia)
            "mk", //  Macedonian
            "mk_MK", //  Macedonian (Macedonia)
            "ms", //  Malay
            "ms_MY", //  Malay (Malaysia)
            "mt", //  Maltese
            "mt_MT", //  Maltese (Malta)
            "nl", //  Dutch
            "nl_BE", //  Dutch (Belgium)
            "nl_NL", //  Dutch (Netherlands)
            "no", //  Norwegian
            "no_NO", //  Norwegian (Norway)
            "no_NO_NY", //  Norwegian (Norway,Nynorsk)
            "pl", //  Polish
            "pl_PL", //  Polish (Poland)
            "pt", //  Portuguese
            "pt_BR", //  Portuguese (Brazil)
            "pt_PT", //  Portuguese (Portugal)
            "ro", //  Romanian
            "ro_RO", //  Romanian (Romania)
            "ru", //  Russian
            "ru_RU", //  Russian (Russia)
            "sk", //  Slovak
            "sk_SK", //  Slovak (Slovakia)
            "sl", //  Slovenian
            "sl_SI", //  Slovenian (Slovenia)
            "sq", //  Albanian
            "sq_AL", //  Albanian (Albania)
            "sr", //  Serbian
            "sr_BA", //  Serbian (Bosnia and Herzegovina)
            "sr_CS", //  Serbian (Serbia and Montenegro)
            "sr_ME", //  Serbian (Montenegro)
            "sr_RS", //  Serbian (Serbia)
            "sv", //  Swedish
            "sv_SE", //  Swedish (Sweden)
            "th", //  Thai
            "th_TH", //  Thai (Thailand)
            "th_TH_TH", //  Thai (Thailand,TH)
            "tr", //  Turkish
            "tr_TR", //  Turkish (Turkey)
            "uk", //  Ukrainian
            "uk_UA", //  Ukrainian (Ukraine)
            "vi", //  Vietnamese
            "vi_VN", //  Vietnamese (Vietnam)
            "zh", //  Chinese
            "zh_CN", //  Chinese (China)
            "zh_HK", //  Chinese (Hong Kong)
            "zh_SG", //  Chinese (Singapore)
            "zh_TW" //  Chinese (Taiwan)
        };
        #endregion

        public static TranslationServer singleton
        {
            get
            {
                return ___singleton;
            }
        }

        public StringName translate(StringName p_message)
        {
            //translate using locale

	        if (!__enabled)
		        return p_message;

	        StringName res = null;
	        bool near_match = false;

	        foreach (Translation E in __translations) 
            {
		        string l = E.get_locale();
		        if (__locale[0] != l[0] || __locale[1] != l[1])
			        continue; // locale not match

		        //near match
		        bool match = (l != __locale);

		        if (near_match && !match)
			        continue; //only near-match once

		        StringName r = E.get_message(p_message);


		        if (r == null)
			        continue;

		        res = r;

		        if (match)
			        break;
		        else
			        near_match=true;
	        }

	        if (res == null)
		        return p_message;

	        return res;
        }

        public void setup()
        {
            set_locale( Globals.global_def("locale/default", OS.singleton.get_locale()) );
	        __fallback = Globals.global_def("locale/fallback","");
	        //load translations
        }

        public string get_locale()
        {
	        return __locale;
        }

        public void set_locale(string p_locale) 
        {
	        //ERR_EXPLAIN("Invalid Locale: "+p_locale);
	        if(!is_valid_locale(p_locale))
                return;
	        __locale = p_locale;
        }

        public void add_translation(Translation p_translation) 
        {
	        __translations.Add(p_translation);
        }

        public void load_translations()
        {
            string locale = get_locale();
            bool found = _load_translations("locale/translations"); //all
            if (_load_translations("locale/translations_" + locale.Substring(0, 2)))
                found = true;
            if (locale.Substring(0, 2) != locale)
            {
                if (_load_translations("locale/translations_" + locale))
                    found = true;
            }


            if (!found && __fallback != "") //none found anywhere, use fallback
            { 
                _load_translations("locale/translations_" + __fallback.Substring(0, 2));
                if (__fallback.Substring(0, 2) != __fallback)
                {
                    _load_translations("locale/translations_" + __fallback);
                }

                this.__locale = __fallback;

            }
        }

        public static bool is_valid_locale(string p_locale) 
        {
            foreach (string e in locale_list)
                if (e == p_locale)
                    return true;
	        return false;
        }

        protected bool _load_translations(string p_from) 
        {
	        if (Globals.singleton.has(p_from)) 
            {
		        List<string> translations = Globals.singleton.get(p_from);

		        int tcount = translations.Count;

		        if (tcount > 0) 
                {			       
			        for(int i = 0; i < tcount; i++) 
                    {
				        //print_line( "Loading translation from " + r[i] );
				        Translation tr = ResourceLoader.load(translations[i]) as Translation;
				        if (tr != null)
					        add_translation(tr);
			        }
		        }
		        return true;
	        }

	        return false;
        }

        public TranslationServer()
        {
            ___singleton = this;
            __enabled = true;
            __locale = "en";
            __translations = new SortedSet<Translation>();
        }

        private bool __enabled;
        private string __locale;
        private string __fallback;
        private SortedSet<Translation> __translations;
        private static TranslationServer ___singleton = null;
    }
}
